using AutoMapper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using ShopPowerTemplate.Entities;
using ShopPowerTemplate.IoC;
using ShopPowerTemplate.Presentation.Mvc.Extensions;
using ShopPowerTemplate.Presentation.Mvc.Models;
using ShopPowerTemplate.Presentation.Mvc.ViewModels;
using ShopPowerTemplate.Services;

namespace ShopPowerTemplate.Presentation.Mvc.Controllers
{
	public partial class ProductDetailControllerBase : BaseController
	{
		#region Members

        protected IProductDetailService _productDetailService;
        protected IProductService _productService;
        protected IOrderDetailService _orderDetailService;
        protected IOrderService _orderService;
        protected IOptionService _optionService;

        #endregion

        #region Constructors

        public ProductDetailControllerBase(IProductDetailService productDetailService, IProductService productService, IOrderDetailService orderDetailService, IOrderService orderService, IOptionService optionService)
        {
            _productDetailService = productDetailService;
            _productService = productService;
            _orderDetailService = orderDetailService;
            _orderService = orderService;
            _optionService = optionService;
        }	

        #endregion

		#region Index

		// **************************************
        // URL: /ProductDetail
        // **************************************
		public virtual ActionResult Index()
		{
			IndexProductDetailViewModel viewModel = new IndexProductDetailViewModel();
			ViewBag.PageIndex = this.GetPageIndex();
            ViewBag.PageSize = this.GetPageSize();
			ViewBag.SearchValue = this.GetSearchValue();
		
			return View(viewModel);
		}

		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult Load(string sidx, string sord, int page, int rows, string search, int mode = 1)
        {
            string searchValue = this.GetSearchValue();
            OrderBy orderBy = this.GetOrderBy();
            int pageIndex = this.GetPageIndex();
            int pageSize = this.GetPageSize();

            if (mode == (int)JQGridActionEnum.DefaultLoad)
            {                
                pageSize = (pageIndex + 1) * pageSize;
                pageIndex = 0;
            }
            else if (mode == (int)JQGridActionEnum.ShowMoreResults)
            {
                pageIndex = page;
                this.SetPageIndex(pageIndex);
            }
            else if (mode == (int)JQGridActionEnum.CustomSearch)
            {
                searchValue = search;
                this.SetSearchValue(searchValue);
                pageIndex = 0;
                this.SetPageIndex(pageIndex);
                orderBy = new OrderBy("", true);
                this.SetOrderBy(orderBy);
            }

            if (!string.IsNullOrEmpty(sidx)) // Sort request
            {
                orderBy = new OrderBy(sidx, sord == "asc");
                this.SetOrderBy(orderBy);
            }

            List<ProductDetail> searchList = _productDetailService.Search(searchValue, orderBy.Property, orderBy.Ascending, pageIndex, pageSize);
            int count = _productDetailService.SearchCount(searchValue);
            
			if (!string.IsNullOrEmpty(sidx)) // Sort request
            {
                pageIndex = this.GetPageIndex();
            }

            var data = new
            {
                total = Math.Ceiling((float)count/(float)pageSize),        // Total pages
                page = pageIndex,      // Current page
                records = count,  // Total records
                rows = from productDetail in searchList     // Row data
                       select new
                       {
                           id = productDetail.Id,                
                           cell = new string[] {
						   
                                productDetail.Stock.ToString(),
								productDetail.Product != null ? productDetail.Product.IdentityDescription : string.Empty
								
                           }
                       }
            };

            return Json(data);
        }

		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult Delete(int id)
        {
            try
            {
                _productDetailService.Remove(id);
            }
            catch (RemoveException ex)
            {
                Response.StatusCode = 500;
                return Content(ex.Message);
            }
            return Content(string.Empty);
        }
		
		public virtual FileContentResult Report()
        {
            IList<ProductDetail> _productDetailList = _productDetailService.Search(this.GetSearchValue());            
            StringBuilder strBuilder = new StringBuilder();

            // columns
            strBuilder.AppendLine("Stock;Product");

            // rows
            foreach (ProductDetail productDetail in _productDetailList)
            {
                List<string> rowData = new List<string>() { productDetail.Stock.ToString(), productDetail.Product != null ? productDetail.Product.IdentityDescription : string.Empty };
                strBuilder.AppendLine(rowData.Aggregate((x, y) => x + ";" + y));
            }

			// encode report content
            System.IO.MemoryStream content = new System.IO.MemoryStream();
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(content, UTF8Encoding.UTF8))
                writer.Write(strBuilder.ToString());

            return File(content.ToArray(), "text/csv", "ProductDetail.csv");
        }
		

		#endregion

		#region Create

		// *******************************************
        // URL: /ProductDetail/Create
        // *******************************************
		[AcceptVerbs(HttpVerbs.Get)]
        public virtual ActionResult Create()
        {
            ProductDetail productDetail = new ProductDetail();
            CreateProductDetailViewModel viewModel = Mapper.Map<ProductDetail, CreateProductDetailViewModel>(productDetail);
            List<Product> allProduct = _productService.FindAll();
            viewModel.ProductList = allProduct;
            
			return View(viewModel);
        }

		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult Create(CreateProductDetailViewModel productDetailModel)
        {
            if (ModelState.IsValid)
            {
                ProductDetail productDetail = new ProductDetail();
                AutoMapper.Mapper.Map<CreateProductDetailViewModel, ProductDetail>(productDetailModel, productDetail);
 

				_productDetailService.Add(productDetail);

                return RedirectToAction("Edit", new { id = productDetail.Id});
            }
            else
            {
				List<Product> allProduct = _productService.FindAll();
				productDetailModel.ProductList = allProduct;

                return View(productDetailModel);
            }
		}
		

		#endregion

		#region Edit

		// *******************************************
        // URL: /ProductDetail/Edit/id
        // *******************************************
		[AcceptVerbs(HttpVerbs.Get)]
        public virtual ActionResult Edit(int id)
        {
            ProductDetail productDetail = _productDetailService.Find(id);
            EditProductDetailViewModel viewModel = Mapper.Map<ProductDetail, EditProductDetailViewModel>(productDetail);
            List<Product> allProduct = _productService.FindAll();
            viewModel.ProductList = allProduct;
				this.SetSearchValue("OptionSearchValue", "");
				this.SetOrderBy("OptionOrderBy", new OrderBy("", true));
				this.SetPageIndex("OptionPageIndex", 0);
				this.SetPageSize("OptionPageSize", 10);				
            
			return View(viewModel);
        }

		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult Edit(EditProductDetailViewModel productDetailModel)
        {
            if (ModelState.IsValid)
            {
                ProductDetail productDetail = _productDetailService.Find(productDetailModel.Id);
                AutoMapper.Mapper.Map<EditProductDetailViewModel, ProductDetail>(productDetailModel, productDetail);
                
				_productDetailService.Change(productDetail);

                return RedirectToAction("Index");
            }
            else
            {
				List<Product> allProduct = _productService.FindAll();
				productDetailModel.ProductList = allProduct;

                return View(productDetailModel);
            }
		}
		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult LoadOrderDetails(string sidx, string sord, int page, int rows, string search, int mode = 1, int masterId = 0)
        {
			ProductDetail currentProductDetail = _productDetailService.Find(masterId);
            List<OrderDetail> list = currentProductDetail.OrderDetails.ToList();
			int count = list.Count();

			var data = new
            {
                total = 1,        // Total pages
                page = 1,      // Current page
                records = count,  // Total records
                rows = from orderDetail in list     // Row data
                       select new
                       {
                           id = orderDetail.Id,                
                           cell = new string[] {
                                orderDetail.Quantity.ToString(),
								orderDetail.Price.ToString(),
								orderDetail.Tax.ToString(),
								orderDetail.Discount.ToString(),
								orderDetail.Order != null ? orderDetail.Order.IdentityDescription : string.Empty
                           }
                       }
            };

            // Return elements
            return Json(data);
        }

		public virtual ActionResult AddOrderDetails(int masterId = 0)
        {
            PopUpOrderDetailViewModel viewModel = new PopUpOrderDetailViewModel();

			List<Order> allOrder = _orderService.FindAll();
			viewModel.OrderList = allOrder;
			viewModel.ProductDetailId = masterId;
			ViewBag.MasterProperty = "ProductDetail";
            ViewBag.Name = "AddOrderDetails";

            return PartialView("~/Views/OrderDetail/PopUp.cshtml", viewModel);
        }
		
		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult AddOrderDetails(PopUpOrderDetailViewModel orderDetailModel)
        {
            if (ModelState.IsValid)
            {
                OrderDetail orderDetails = new OrderDetail();
                AutoMapper.Mapper.Map<PopUpOrderDetailViewModel, OrderDetail>(orderDetailModel, orderDetails);

				ProductDetail productDetail = _productDetailService.Find(orderDetails.ProductDetail.Id);
				_productDetailService.AddOrderDetails(productDetail, orderDetails);
                
				Response.StatusCode = 200;
                return Content("OK", "text/plain");
            }
            else
            {
				List<Order> allOrder = _orderService.FindAll();
				orderDetailModel.OrderList = allOrder;
				ViewBag.MasterProperty = "ProductDetail";
            	ViewBag.Name = "AddOrderDetails";


				return PartialView("~/Views/OrderDetail/PopUp.cshtml", orderDetailModel);
            }
        }	
		
		public virtual ActionResult EditOrderDetails(int id, int masterId = 0)
        {
			OrderDetail orderDetail = _orderDetailService.Find(id);
            PopUpOrderDetailViewModel viewModel = Mapper.Map<OrderDetail, PopUpOrderDetailViewModel>(orderDetail);

			List<Order> allOrder = _orderService.FindAll();
			List<ProductDetail> allProductDetail = _productDetailService.FindAll();
			viewModel.OrderList = allOrder;
			viewModel.ProductDetailId = masterId;
			ViewBag.MasterProperty = "ProductDetail";
            ViewBag.Name = "EditOrderDetails";

            return PartialView("~/Views/OrderDetail/PopUp.cshtml", viewModel);
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult EditOrderDetails(PopUpOrderDetailViewModel orderDetailModel)
        {
            if (ModelState.IsValid)
            {
                OrderDetail orderDetail = _orderDetailService.Find(orderDetailModel.Id);
                AutoMapper.Mapper.Map<PopUpOrderDetailViewModel, OrderDetail>(orderDetailModel, orderDetail);

                _orderDetailService.Change(orderDetail);

                Response.StatusCode = 200;
                return Content("OK", "text/plain");
            }
            else
            {
				List<Order> allOrder = _orderService.FindAll();
				List<ProductDetail> allProductDetail = _productDetailService.FindAll();
				orderDetailModel.OrderList = allOrder;
				orderDetailModel.ProductDetailList = allProductDetail;
				ViewBag.MasterProperty = "ProductDetail";

                return PartialView("~/Views/OrderDetail/PopUp.cshtml", orderDetailModel);
            }
        }
		
		[AcceptVerbs(HttpVerbs.Post)]
        public virtual void DeleteOrderDetails(int id, int masterId = 0)
        {
			OrderDetail orderDetail = _orderDetailService.Find(id);
			ProductDetail currentProductDetail = _productDetailService.Find(masterId);

            _productDetailService.RemoveOrderDetails(currentProductDetail, orderDetail);
        }
			
		public virtual FileContentResult ReportOrderDetails(int masterId = 0)
        {
			ProductDetail currentProductDetail = _productDetailService.Find(masterId);
            IList<OrderDetail> _orderDetailsList = currentProductDetail.OrderDetails.ToList();          
            StringBuilder strBuilder = new StringBuilder();

            // columns
            strBuilder.AppendLine("Quantity;Price;Tax;Discount;Order");

            // rows
            foreach (OrderDetail orderDetail in _orderDetailsList)
            {
                List<string> rowData = new List<string>() { orderDetail.Quantity.ToString(), orderDetail.Price.ToString(), orderDetail.Tax.ToString(), orderDetail.Discount.ToString(), orderDetail.Order != null ? orderDetail.Order.IdentityDescription : string.Empty };
                strBuilder.AppendLine(rowData.Aggregate((x, y) => x + ";" + y));
            }

			// encode report content
            System.IO.MemoryStream content = new System.IO.MemoryStream();
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(content, UTF8Encoding.UTF8))
                writer.Write(strBuilder.ToString());

            return File(content.ToArray(), "text/csv", "OrderDetails.csv");
        }
		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult LoadSelectedOption(string sidx, string sord, int page, int rows, string search, int mode = 1, int masterId = 0)
        {
			ProductDetail currentProductDetail = _productDetailService.Find(masterId);
            List<Option> list = currentProductDetail.Option.ToList();
			int count = list.Count();

			var data = new
            {
                total = 1,        // Total pages
                page = 1,      // Current page
                records = count,  // Total records
                rows = from option in list     // Row data
                       select new
                       {
                           id = option.Id,                
                           cell = new string[] {
                                option.Name,
								option.Description,
								option.OptionType != null ? option.OptionType.IdentityDescription : string.Empty
                           }
                       }
            };

            // Return elements
            return Json(data);
        }

		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult LoadAvailablesOption(string sidx, string sord, int page, int rows, string search, int mode = 1, int masterId = 0)
        {
			string searchValue = this.GetSearchValue("OptionSearchValue");
            OrderBy orderBy = this.GetOrderBy("OptionOrderBy");
            int pageIndex = this.GetPageIndex("OptionPageIndex");
            int pageSize = this.GetPageSize("OptionPageSize");

            if (mode == (int)JQGridActionEnum.DefaultLoad)
            {
                pageSize = (pageIndex + 1) * pageSize;
                pageIndex = 0;
            }
            else if (mode == (int)JQGridActionEnum.ShowMoreResults)
            {
                pageIndex = page;
                this.SetPageIndex("OptionPageIndex", pageIndex);
            }
            else if (mode == (int)JQGridActionEnum.CustomSearch)
            {
                searchValue = search;
                this.SetSearchValue("OptionSearchValue", searchValue);
                pageIndex = 0;
                this.SetPageIndex("OptionPageIndex", pageIndex);
                orderBy = new OrderBy("", true);
                this.SetOrderBy("OptionOrderBy", orderBy);
            }

            ProductDetail currentProductDetail = _productDetailService.Find(masterId);
            List<Option> searchList = _optionService.FindAvailableOptionList(currentProductDetail.Option.ToList(), search, x => x.Id, true, pageIndex, pageSize);
            int count = _optionService.FindAvailableOptionListCount(currentProductDetail.Option.ToList(), search);

            var data = new
            {
                total = Math.Ceiling((float)count / (float)pageSize),        // Total pages
                page = pageIndex,      // Current page
                records = count,  // Total records
                rows = from option in searchList     // Row data
                       select new
                       {
                           id = option.Id,
                           cell = new string[] {
                                option.Name,
								option.Description,
								option.OptionType != null ? option.OptionType.IdentityDescription : string.Empty
                           }
                       }
            };

            return Json(data);
        }

		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult AddOption(int[] ids, int masterId = 0)
        {
			if(ids != null)
			{
				ProductDetail currentProductDetail = _productDetailService.Find(masterId);

				foreach (int id in ids)
				{
					Option addOption = _optionService.Find(id);
					_productDetailService.AddOption(currentProductDetail, addOption);
				}
			}
			
			Response.StatusCode = 200;
			return Content("200", "text/plain");
		}

		[AcceptVerbs(HttpVerbs.Post)]
        public virtual ActionResult RemoveOption(int id, int masterId)
        {
			ProductDetail currentProductDetail = _productDetailService.Find(masterId);
            Option removeOption = _optionService.Find(id);
            _productDetailService.RemoveOption(currentProductDetail, removeOption);

			Response.StatusCode = 200;
			return Content("200", "text/plain");
		}
		
		public virtual FileContentResult ReportOption(int masterId = 0)
        {
			ProductDetail currentProductDetail = _productDetailService.Find(masterId);
            IList<Option> _optionList = currentProductDetail.Option.ToList();          
            StringBuilder strBuilder = new StringBuilder();

            // columns
            strBuilder.AppendLine("Name;Description;OptionType");

            // rows
            foreach (Option option in _optionList)
            {
                List<string> rowData = new List<string>() { option.Name, option.Description, option.OptionType != null ? option.OptionType.IdentityDescription : string.Empty };
                strBuilder.AppendLine(rowData.Aggregate((x, y) => x + ";" + y));
            }

			// encode report content
            System.IO.MemoryStream content = new System.IO.MemoryStream();
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(content, UTF8Encoding.UTF8))
                writer.Write(strBuilder.ToString());

            return File(content.ToArray(), "text/csv", "Option.csv");
        }
		

		#endregion

		#region Details

		// *******************************************
        // URL: /ProductDetail/Details/id
        // *******************************************
		[AcceptVerbs(HttpVerbs.Get)]
        public virtual ActionResult Details(int id)
        {
            ProductDetail productDetail = _productDetailService.Find(id);
            DetailsProductDetailViewModel viewModel = Mapper.Map<ProductDetail, DetailsProductDetailViewModel>(productDetail);
            
			return View(viewModel);
        }
		

		#endregion
	}
}
